//
// Created by Jisam on 04/10/2024 11:51 PM.
// Solution of  P1312 Mayan游戏
// 2024-10-05 00:24:56  AC 100 模拟 + dfs + 剪枝
#include <bits/stdc++.h>  // 包含标准库，bits/stdc++.h 是一个非标准的头文件，包含了几乎所有标准库

#define int long long  // 定义 int 为 long long 类型，用于处理大整数
#define endl "\n"  // 定义 endl 为换行符

using namespace std;  // 使用标准命名空间

// 读取一个整数
inline int read() {
    int x = 0, f = 1;  // x 用于存储结果，f 用于处理负号
    char ch = getchar();  // 读取一个字符
    while (ch < '0' || ch > '9') {  // 忽略非数字字符
        if (ch == '-')
            f = -1;  // 如果是负号，设置 f 为 -1
        ch = getchar();  // 继续读取下一个字符
    }
    while (ch >= '0' && ch <= '9') {  // 读取数字字符
        x = (x << 1) + (x << 3) + (ch ^ 48);  // 将字符转换为数字并累加
        ch = getchar();  // 继续读取下一个字符
    }
    return x * f;  // 返回最终结果，考虑负号
}

// 定义一个结构体，用于存储坐标和方向
struct node {
    int x, y, z;
} c[7];  // 定义一个数组 c，用于存储操作步骤

int n, a[7][9], b[7][7][9];  // n 存储操作次数，a 存储当前状态，b 存储备份状态

queue<node> q;  // 定义一个队列，用于存储消去操作

// 备份当前状态到 b[k]
void fz(int k) {
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 7; j++) {
            b[k][i][j] = a[i][j];
        }
    }
}

// 从 b[k] 恢复当前状态
void huanyuan(int k) {
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 7; j++) {
            a[i][j] = b[k][i][j];
        }
    }
}

// 检查并执行消去操作
bool xiaochu() {
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 7; j++) {
            if (a[i][j] && a[i - 1][j] == a[i][j] && a[i + 1][j] == a[i][j])
                q.push({i, j, 0});  // 垂直消去
            if (a[i][j] && a[i][j - 1] == a[i][j] && a[i][j + 1] == a[i][j])
                q.push({i, j, 1});  // 水平消去
        }
    }
    if (q.empty()) return 0;  // 如果没有消去操作，返回 false
    while (!q.empty()) {
        node k = q.front();  // 获取队列前端元素
        q.pop();
        if (k.z)
            a[k.x][k.y] = a[k.x][k.y - 1] = a[k.x][k.y + 1] = 0;  // 水平消去
        else
            a[k.x][k.y] = a[k.x - 1][k.y] = a[k.x + 1][k.y] = 0;  // 垂直消去
    }
    return 1;  // 有消去操作，返回 true
}

// 执行下落操作
void dieluo() {
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 7; j++) {
            if (a[i][j] && !a[i][j - 1]) {  // 如果当前位置有球，且左边没有球
                for (int k = j - 1; k >= 0; k--) {  // 向左查找空位
                    if (a[i][k]) {  // 找到球，交换位置
                        swap(a[i][j], a[i][k + 1]);
                        break;
                    }
                }
            }
        }
    }
}

// 执行移动操作
void yidong(int x, int y, int k) {
    swap(a[x][y], a[x + k][y]);  // 交换球的位置
    if (!a[x][y]) dieluo();  // 如果交换后左边没有球，执行下落操作
    while (xiaochu()) dieluo();  // 执行消去操作，直到没有可以消去的球
}

// 检查是否完成游戏
bool jiancha() {
    for (int i = 1; i <= 5; i++) {
        if (a[i][1]) return 0;  // 如果第一列还有球，返回 false
    }
    return 1;  // 完成游戏，返回 true
}

// 深度优先搜索
void dfs(int k) {
    if (!k) {  // 如果没有剩余操作次数
        if (jiancha()) {  // 如果完成游戏
            for (int i = n; i > 0; i--) {  // 打印操作步骤
                printf("%d %d %d\n", c[i].x - 1, c[i].y - 1, c[i].z);
            }
            exit(0);  // 退出程序
        }
        return;
    }
    fz(k);  // 备份当前状态
    bool flag = 0;
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 7; j++) {
            if (a[i][j]) {  // 如果当前位置有球
                if (i > 1 && !a[i - 1][j]) {  // 如果可以向上移动
                    yidong(i, j, -1);  // 执行向上移动
                    c[k] = {i, j, -1};  // 记录操作步骤
                    dfs(k - 1);  // 递归搜索
                    huanyuan(k);  // 恢复状态
                }
                if (i < 5) {
                    if (a[i][j] == a[i + 1][j] && flag) continue;  // 如果已经尝试过相同的移动
                    if (a[i][j] == a[i + 1][j]) flag = 1;  // 标记已经尝试过
                    yidong(i, j, 1);  // 执行向下移动
                    c[k] = {i, j, 1};  // 记录操作步骤
                    dfs(k - 1);  // 递归搜索
                    huanyuan(k);  // 恢复状态
                }
            }
        }
    }
}

// 主函数
signed main() {
    n = read();  // 读取操作次数
    for (int i = 1; i <= 5; i++)
        a[i][0] = 2147483647;  // 初始化边界
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 8; j++) {
            a[i][j] = read();  // 读取初始状态
            if (!a[i][j]) break;  // 如果读到0，结束这一行的读取
        }
    }
    dfs(n);  // 执行深度优先搜索
    puts("-1");
//    cout << -1;  // 如果没有找到解决方案，输出 -1
    return 0;
}